package com.bjtu.literatureclient.shiro;

import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Shiro配置类
 *
 */
@Configuration
public class ShiroConfig {
    /**
     * ShiroFilterFactoryBean 处理拦截资源文件问题。
     * 注意：单独一个ShiroFilterFactoryBean配置是或报错的，以为在
     * 初始化ShiroFilterFactoryBean的时候需要注入：SecurityManager
     *
     * Filter Chain定义说明 1、一个URL可以配置多个Filter，使用逗号分隔 2、当设置多个过滤器时，全部验证通过，才视为通过
     * 3、部分过滤器可指定参数，如perms，roles
     *
     */
    @Bean(name="shiroFilter")
    public ShiroFilterFactoryBean shirFilter(@Qualifier("securityManager") SecurityManager securityManager) {
    	System.out.println("配置过滤器...");
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // 登录页面，无权限时跳转的路径
        shiroFilterFactoryBean.setLoginUrl("/index.html");
        // 登录成功后跳转的路径
        // shiroFilterFactoryBean.setSuccessUrl("/");
        // 错误页面，认证不通过跳转
        shiroFilterFactoryBean.setUnauthorizedUrl("/403.html");


        
        Map<String, Filter> filters = shiroFilterFactoryBean.getFilters();//获取filters
        MyFormAuthenticationFilter authFilter=new MyFormAuthenticationFilter();
        authFilter.setLoginUrl("/user/login");
		filters.put("authc", authFilter);//将自定义 的FormAuthenticationFilter注入shiroFilter中 
		filters.put("perms", new CustomPermissionsAuthorizationFilter());
		filters.put("logout", new SystemLogoutFilter());
		shiroFilterFactoryBean.setFilters(filters);


        // 配置拦截规则
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();

        // 配置退出过滤器,其中的具体的退出代码Shiro已经替我们实现了
        filterChainDefinitionMap.put("/user/logout", "logout");


		// anno: 表示可以匿名使用。
		filterChainDefinitionMap.put("/teamAdminRegister.html","anon");
		filterChainDefinitionMap.put("/selfAdminRegister.html","anon");
		filterChainDefinitionMap.put("/swagger-ui.html","anon");
        filterChainDefinitionMap.put("/index.html", "anon");
        filterChainDefinitionMap.put("/user/addteamuser","anon");
        filterChainDefinitionMap.put("/team/getNewTeamNo","anon");
        filterChainDefinitionMap.put("/team/addTeamAndAdmin","anon");
        filterChainDefinitionMap.put("/user/checkUserEmail","anon");
        filterChainDefinitionMap.put("/team/checkTeamEmail","anon");
        filterChainDefinitionMap.put("index.html","anon");
        filterChainDefinitionMap.put("/user/update","anon");
        
        /*filterChainDefinitionMap.put("/application2.html", "authc");*/
		
        // authc: 表示需要认证(登录)才能使用
        filterChainDefinitionMap.put("/user/","authc");
        filterChainDefinitionMap.put("/user/login","authc");

        
        //新加这两句
        filterChainDefinitionMap.put("/admin/**", "perms[superAdmin,teamAdmin]");
        //filterChainDefinitionMap.put("/admin/**", "perms[teamAdmin]");
        filterChainDefinitionMap.put("/miuser/**", "perms[superUser,highUser,middleUser]");
       /* filterChainDefinitionMap.put("/miuser/**", "perms[highUser]");
        filterChainDefinitionMap.put("/miuser/**", "perms[middleUser]");*/
        
        //filterChainDefinitionMap.put("/user/login","anon");
        //filterChainDefinitionMap.put("/index.html","logout");
        filterChainDefinitionMap.put("/","anon");

        //2.不拦截的请求

        filterChainDefinitionMap.put("/css/**","anon");
        filterChainDefinitionMap.put("/data/**","anon");
        filterChainDefinitionMap.put("/font/**","anon");
        filterChainDefinitionMap.put("/fonts/**","anon");
        filterChainDefinitionMap.put("/images/**","anon");
        filterChainDefinitionMap.put("/journaljs/**","anon");
        filterChainDefinitionMap.put("/jqgrid/**","anon");
        filterChainDefinitionMap.put("/js/**","anon");
        filterChainDefinitionMap.put("/**.ico","anon");
        //swagger
        filterChainDefinitionMap.put("/webjars/**","anon");
        filterChainDefinitionMap.put("/swagger-resources/**","anon");
        filterChainDefinitionMap.put("/v2/**","anon");


        
        // 过滤链定义，从上向下顺序执行，一般将 /**放在最为下边 :这是 坑呢，一不小心代码就不好使了;
        // ① authc:所有url都必须认证通过才可以访问; ② anon:所有url都都可以匿名访问*/
        //filterChainDefinitionMap.put("/static/**", "anon");
        filterChainDefinitionMap.put("/**", "authc");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

    // 安全管理器
    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 设置realm.
        securityManager.setRealm(myRealm());
        // securityManager.setRememberMeManager(null);
        return securityManager;
    }

    /**
     * 身份认证realm; (这个需要自己写，账号密码校验；权限等)
     * 
     * @return
     */
    @Bean
    public UserRealm myRealm() {
    	UserRealm myRealm = new UserRealm();
        return myRealm;
    }

    /**
     * Shiro生命周期处理器
     * @return
     */
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    /**
     * 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证
     * 配置以下两个bean(DefaultAdvisorAutoProxyCreator(可选)和AuthorizationAttributeSourceAdvisor)即可实现此功能
     * @return
     */
    @Bean
    @DependsOn({ "lifecycleBeanPostProcessor" })
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
        return authorizationAttributeSourceAdvisor;
    }
    
}

